#!/usr/bin/env perl
#
# Stark Fist of Retrieval - Perl script to backup/manage network hosts (eg Cisco)
#
# by Josh Matthews <shazburg@gmail.com>
#
# http://code.google.com/p/stark-fist-of-retrieval
#
use strict;
use Net::Telnet::Cisco;
use YAML::Tiny;

my $yaml = YAML::Tiny->read('./hosts.yml');
print YAML::Tiny->errstr;

# YAML starts as an array of hashes (of hashes)
my $hash = $yaml->[0];

# Make sure we have the latest configs from svn
print "Make sure we have current scripts: ";
system( 'svn', 'up', './configs' );

for my $host_name ( sort keys %$hash ) {

    my $type     = $hash->{$host_name}{'type'};
    my $password = $hash->{$host_name}{'password'};
    my $enable   = $hash->{$host_name}{'enable'};
    my @config;

    print "Backing up $type $host_name ";

    if ( my $session = Net::Telnet::Cisco->new( Host => $host_name ) ) {

        # Useful for debugging
        # $session->input_log("logs/$host_name");

        # PIX prompt has an extra whitespace. Prompt is not specifed in $session
        # creation because I'd rather not break Keroes' prompt: I trust him more
        # than myself.
        if ( $type eq 'pix' ) {
            $session->prompt('/[\$%#>] $/');
        }

        $session->login( Password => $password );
        $session->enable($enable);

        # PIX uses a unique command to handle pagination.
        if ( $type eq 'pix' ) {
            $session->cmd('no pager');
        }

        @config = $session->cmd('show running');

        $session->close;
    }

    my $output_filename = $type . "_" . $host_name;
    open( OUTPUT, ">configs/$output_filename" );

    # Can I just write() without open/close?
    print OUTPUT @config;
    close(OUTPUT);

    print "... done!\n";
}

print
"All configs have been copied (or at least we tried). Check-in to Subversion:\n";
system( 'svn', 'add', './configs/*' );
system( 'svn', 'ci', './configs', '-m', '* Auto-update by Pilot' );

